package cs236369.webserver;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Properties;

import org.xml.sax.InputSource;

public class Config {
	public String base = null;
	public String port = null;
	public int socketReaders = 0;
	public int requestHandlers = 0;
	public int socketQueueSize = 0;
	public int requestQueueSize = 0;
	public HashMap<String, TypeHandlerProperties> handlerMap = new HashMap<String, TypeHandlerProperties>();
	public HashMap<String, String> mimeMap = new HashMap<String, String>();
	public String welcomeFile = null;

	public Config(InputStream _config) throws Exception {
		DocumentBuilderFactory docFactory = DocumentBuilderFactory
				.newInstance();
		docFactory.setNamespaceAware(true);
		DocumentBuilder builder = docFactory.newDocumentBuilder();
		Document doc = builder.parse(new InputSource(_config));
		XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		// running a simple query
		base = xpath.compile("//server-config/@base").evaluate(doc);
		port = xpath.compile("//server-config/@port").evaluate(doc);
		socketReaders = Integer.parseInt(xpath.compile(
				"//server-config/threads/socket-readers/multi/text()")
				.evaluate(doc));
		requestHandlers = Integer.parseInt(xpath.compile(
				"//server-config/threads/request-handlers/multi/text()")
				.evaluate(doc));
		socketQueueSize = Integer.parseInt(xpath.compile(
				"//server-config/queues/socket-queue/size/text()")
				.evaluate(doc));
		requestQueueSize = Integer.parseInt(xpath.compile(
				"//server-config/queues/request-queue/size/text()").evaluate(
				doc));
		welcomeFile = xpath.compile("//server-config/welcome-file/text()")
				.evaluate(doc);

		// Working on the type-handler nodes.
		NodeList handlerList = (NodeList) xpath.compile(
				"//type-handlers/type-handler").evaluate(doc,
				XPathConstants.NODESET);
		for (int i = 0; i < handlerList.getLength(); ++i) {
			String className = null;
			className = xpath.compile("./@class").evaluate(handlerList.item(i));
			NodeList el = (NodeList) xpath.compile("./extension").evaluate(
					handlerList.item(i), XPathConstants.NODESET);
			for (int j = 0; j < el.getLength(); j++) {
				String extension = xpath.compile("./text()").evaluate(
						el.item(j));
				if (extension != null) {
					handlerMap.put(
							extension,
							new TypeHandlerProperties(className,
									(NodeList) xpath.compile("./parameter")
											.evaluate(handlerList.item(i),
													XPathConstants.NODESET)));
				}
			}
		}
		NodeList mimeList = (NodeList) xpath.compile("//mime/mime-mapping")
				.evaluate(doc, XPathConstants.NODESET);
		for (int i = 0; i < mimeList.getLength(); ++i) {
			String extension = null;
			String mimeType = null;
			extension = xpath.compile("./extension/text()").evaluate(
					mimeList.item(i));
			mimeType = xpath.compile("./mime-type/text()").evaluate(
					mimeList.item(i));
			mimeMap.put(extension, mimeType);
		}
		Log.out("Config: done parsing");
	}

}

class Parameter {
	String name;
	String value;

	Parameter(String _name, String _value) {
		name = _name;
		value = _value;
	}

	String getName() {
		return name;
	}

	String getValue() {
		return value;
	}

	void setName(String _name) {
		name = _name;
	}

	void setValue(String _value) {
		value = _value;
	}
}

class TypeHandlerProperties {
	String className;
	Properties props;

	TypeHandlerProperties(String _class, NodeList _params)
			throws XPathExpressionException {
		props = new Properties();
		XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		className = _class;
		for (int i = 0; i < _params.getLength(); ++i) {
			String name = xpath.compile("./@name").evaluate(_params.item(i));
			String value = xpath.compile("./@value").evaluate(_params.item(i));
			props.setProperty(name, value);
		}
	}

	String getClassName() {
		return className;
	}

	Properties getProperties() {
		return props;
	}
}